package com.tuling.controller;


import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

@Controller
public class UploadController {

    private Map<String, Set<Integer>> cache = new HashMap<String,  Set<Integer>>();
    private final static String utf8 ="utf-8";

    @RequestMapping("/upload")
    @ResponseBody
    public void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {

        //分片
        response.setCharacterEncoding(utf8);
        // 当前是第几个分片
        Integer schunk = null;
        // 总分片数
        Integer schunks = null;
        // 文件名称
        String name = null;
        String id = null;
        // 上传目录
        String uploadPath = "F:\\fileItem";
        BufferedOutputStream os = null;
        try{
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(1024);
            factory.setRepository(new File(uploadPath));

            ServletFileUpload upload = new ServletFileUpload(factory);
            // 单个分片文件的大小限制
            upload.setFileSizeMax(5L * 1024L * 1024L * 1024L);
            // 总文件大小限制
            upload.setSizeMax(10L * 1024L * 1024L * 1024L);
            List<FileItem> items = upload.parseRequest(request);

            for(FileItem item : items){
                // 1. 如果FileItem表示表单字段，则取根据字段名chunk、chunks、name，取出对应的字段值
                if( item.isFormField() ){
                    if("chunk".equals(item.getFieldName())){
                        schunk = Integer.parseInt(item.getString(utf8));
                    }
                    if("chunks".equals(item.getFieldName())){
                        schunks = Integer.parseInt(item.getString(utf8));
                    }
                    if("name".equals(item.getFieldName())){
                        name = item.getString(utf8);
                    }
                    if("id".equals(item.getFieldName())){
                        id = item.getString(utf8);
                    }
                }
            }

            for(FileItem item : items){
                // 2. 如果FileItem表示表示一个文件
                if( !item.isFormField() ){
                    String temFileName = name;
                    if(name != null){
                        // 如果有分片，文件名为：分片索引_文件名
                        if(schunk != null){
                            temFileName = schunk +"_"+name;
                        }
                        // 创建一个文件临时文件，将内容写入临时文件
                        File temFile = new File(uploadPath,temFileName);
                        if( !temFile.exists() ){//断点续传
                            item.write(temFile);
                        }
                    }
                }
            }

            //3. 如果有分片chunk，并且分片chunk刚好等于最后一个分片(总分片数-1)，则进行文件合并, 总分片数-1 因为分片数是从0开始
            if( schunk != null && (schunk.intValue() == schunks.intValue()-1) ){
                File file = new File(uploadPath,name);
                os = new BufferedOutputStream(new FileOutputStream(file));

                // 逐一取出分片1，分片2...进行写入到最终的输出流中，并且删除分片
                for(int i = 0; i < schunks; i++){
                    File tempFile = new File(uploadPath,i+"_"+name);
                    while( !tempFile.exists() ){
                        Thread.sleep(100);
                    }
                    byte[] bytes = FileUtils.readFileToByteArray(tempFile);
                    os.write(bytes);
                    os.flush();
                    tempFile.delete();
                }
                os.flush();
            }

            /*if (id != null){
                Set<Integer> finishChunks = cache.get(id);
                if (finishChunks == null){
                    finishChunks = new HashSet<>();
                }
                finishChunks.add(schunk);
                cache.put(id, finishChunks);
            }*/

            response.getWriter().write("上传成功"+name);

        }finally {
            try{
                if(os != null){
                    os.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }

    }

    /*@RequestMapping("/query")
    @ResponseBody
    public ApiResult query(String id) throws Exception {
        Set<Integer> finishChunks = cache.get(id);
        return new ApiResult.Builder().success(finishChunks).build();
    }*/
}
